using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Resources;
using System.Reflection;
using System.Diagnostics;

namespace PasteAsText
{	
	/// <summary>
	/// This window is always hidden and is just here for convenience. The WndProc
	/// of this window is overridden to handle clipboard events we're interested in.
	/// </summary>
	public class Configuration : System.Windows.Forms.Form
	{
		private System.ComponentModel.IContainer components;
		private IntPtr _ClipboardViewerNext;

		#region Windows Message Constants
		private const int WM_DRAWCLIPBOARD = 0x0308;		
		private const int WM_CHANGECBCHAIN = 0x030D;
		#endregion

		private System.Windows.Forms.NotifyIcon ni;
		private System.Windows.Forms.ContextMenu mnu;
		private System.Windows.Forms.MenuItem mnuAutomatic;
		private System.Windows.Forms.MenuItem mnuExit;

		public Configuration()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		[DllImport("User32.dll")]
		private static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);

		[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
		private static extern IntPtr SendMessage(HandleRef hWnd, int Msg, IntPtr wParam, IntPtr lParam);

		[DllImport("user32.dll")]
		private static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);

		protected override void WndProc(ref Message m)
		{		
			try
			{
				switch(m.Msg)
				{
					case WM_DRAWCLIPBOARD:
						_SetPlainText();
						SendMessage(new HandleRef(this, _ClipboardViewerNext), m.Msg, m.WParam, m.LParam);
						break;

					case WM_CHANGECBCHAIN:
						if (m.WParam == _ClipboardViewerNext)
						{
							_ClipboardViewerNext = m.LParam;
						}
						else
						{
							SendMessage(new HandleRef(this, this.Handle), m.Msg, m.WParam, m.LParam);
						}
						break;

					default:
						base.WndProc (ref m);
						break;
				}
			}
			catch(Exception ex)
			{
				Trace.WriteLine("Exception: " + ex.Message + ", " + ex.StackTrace);
			}
		}


		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			this.ni = new System.Windows.Forms.NotifyIcon(this.components);
			this.mnu = new System.Windows.Forms.ContextMenu();
			this.mnuAutomatic = new System.Windows.Forms.MenuItem();
			this.mnuExit = new System.Windows.Forms.MenuItem();
			// 
			// ni
			// 
			this.ni.ContextMenu = this.mnu;
			this.ni.Text = "Paste as text";
			this.ni.Visible = true;
			this.ni.DoubleClick += new System.EventHandler(this.ni_DoubleClick);
			this.ni.Click += new System.EventHandler(this.ni_Click);
			// 
			// mnu
			// 
			this.mnu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																				this.mnuAutomatic,
																				this.mnuExit});
			// 
			// mnuAutomatic
			// 
			this.mnuAutomatic.Checked = true;
			this.mnuAutomatic.Index = 0;
			this.mnuAutomatic.Text = "&Automatic";
			this.mnuAutomatic.Click += new System.EventHandler(this.mnuAutomatic_Click);
			// 
			// mnuExit
			// 
			this.mnuExit.Index = 1;
			this.mnuExit.Text = "E&xit";
			this.mnuExit.Click += new System.EventHandler(this.mnu_Exit);
			// 
			// Configuration
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(284, 264);
			this.Name = "Configuration";
			this.ShowInTaskbar = false;
			this.Text = "Configuration";
			this.WindowState = System.Windows.Forms.FormWindowState.Minimized;
			this.Load += new System.EventHandler(this.Configuration_Load);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new Configuration());
		}

		private void _SetPlainText()
		{
			Trace.WriteLine("_SetPlainText");
			IDataObject data = Clipboard.GetDataObject();			
			if(data.GetDataPresent(DataFormats.Text))
			{
				string text = data.GetData(DataFormats.Text) as string;
				Clipboard.SetDataObject(text);
			}
		}

		private void _StartClipboardMonitoring()
		{
			Trace.WriteLine("_StartClipboardMonitoring");
			_ClipboardViewerNext = SetClipboardViewer(this.Handle);
			mnuAutomatic.Checked = true;
			_SetEnabledIcon();
		}

		private void _StopClipboardMonitoring()
		{
			Trace.WriteLine("_StopClipboardMonitoring");
			ChangeClipboardChain(this.Handle, _ClipboardViewerNext);
			mnuAutomatic.Checked = false;
			_SetDisabledIcon();
		}

		private void _SetEnabledIcon()
		{
			Trace.WriteLine("_SetEnabledIcon");
			ni.Icon = new Icon(Assembly.GetExecutingAssembly().GetManifestResourceStream("PasteAsText.App.ico"));
		}

		private void _SetDisabledIcon()
		{
			Trace.WriteLine("_SetDisabledIcon");
			ni.Icon = new Icon(Assembly.GetExecutingAssembly().GetManifestResourceStream("PasteAsText.AppDisabled.ico"));
		}

		private void _ToggleStatus()
		{
			Trace.WriteLine("_ToggleStatus");
			if(mnuAutomatic.Checked)
			{
				_StopClipboardMonitoring();
			}
			else
			{
				_StartClipboardMonitoring();
				_SetPlainText();
			}
		}

		private void mnu_Exit(object sender, EventArgs e)
		{	
			try
			{
				_StopClipboardMonitoring();
				ni.Visible = false;
				ni.Dispose();
				Application.Exit();
			}
			catch(Exception ex)
			{
				Trace.WriteLine("Exception: " + ex.Message + ", " + ex.StackTrace);
			}
		}

		private void Configuration_Load(object sender, System.EventArgs e)
		{
			try
			{
				_StartClipboardMonitoring();
			}
			catch(Exception ex)
			{
				Trace.WriteLine("Exception: " + ex.Message + ", " + ex.StackTrace);
			}
		}

		private void mnuAutomatic_Click(object sender, System.EventArgs e)
		{
			try
			{
				_ToggleStatus();
			}
			catch(Exception ex)
			{
				Trace.WriteLine("Exception: " + ex.Message + ", " + ex.StackTrace);
			}
		}

		private void ni_Click(object sender, System.EventArgs e)
		{
			try
			{
				if(mnuAutomatic.Checked == false)
				{
					_SetPlainText();
				}
			}
			catch(Exception ex)
			{
				Trace.WriteLine("Exception: " + ex.Message + ", " + ex.StackTrace);
			}
		}

		private void ni_DoubleClick(object sender, System.EventArgs e)
		{
			try
			{
				_ToggleStatus();
			}
			catch(Exception ex)
			{
				Trace.WriteLine("Exception: " + ex.Message + ", " + ex.StackTrace);
			}
		}
	}
}
